package com.mdb.open.trade.facade;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.mdb.bc.api.data.ResultEx;
import com.mdb.bc.utils.ObjectUtil;
import com.mdb.bc.utils.security.SignUtil;
import com.mdb.enums.PlatformRetCodeEnum;
import com.mdb.enums.ReqHeaderKeyEnum;
import com.mdb.open.common.enums.product.ProdDockingTypeEnum;
import com.mdb.open.common.enums.product.ProductOpenStatusEnum;
import com.mdb.open.trade.config.MdbProdProperties;
import com.mdb.open.trade.config.TradeOpenProperties;
import com.mdb.open.trade.domain.dto.product.SetWhiteListDto;
import com.mdb.open.trade.domain.dto.product.SignDto;
import com.mdb.open.trade.domain.dto.product.VerifySignDto;
import com.mdb.open.trade.domain.po.product.CustProd;
import com.mdb.open.trade.domain.po.product.CustProdConfig;
import com.mdb.open.trade.domain.vo.product.CustProdConfigVo;
import com.mdb.open.trade.domain.vo.product.CustProdDetailVo;
import com.mdb.open.trade.feign.UserServiceClient;
import com.mdb.open.trade.feign.vo.UserVo;
import com.mdb.open.trade.service.product.CustProdConfigService;
import com.mdb.open.trade.service.product.CustProdService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author liuyi
 * @date 2019/07/13
 **/
@Service
public class CustProdFacade {

    @Autowired
    private CustProdConfigService custProdConfigService;

    @Autowired
    private CustProdService custProdService;

    @Autowired
    private TradeOpenProperties tradeOpenProperties;

    @Autowired
    private MdbProdProperties mdbProdProperties;

    @Autowired
    private UserServiceClient userServiceClient;
    /**
     * 根据appId产品app配置信息
     */
    public ResultEx<CustProdConfigVo> getAppConfigByAppId(String appId) {
        ResultEx<CustProdDetailVo> checkOpenApiAuth = this.checkOpenApiAuth(appId);
        if (checkOpenApiAuth.isFailed()) {
            return ResultEx.makeResult(checkOpenApiAuth.getRetCode(), checkOpenApiAuth.getRetMsg());
        }
        CustProdDetailVo custProdDetailVo = checkOpenApiAuth.getData();

        ResultEx<UserVo> userVoResultEx = userServiceClient.queryUserInfoByCustomerCode(custProdDetailVo.getCustomerCode());
        UserVo userVo = userVoResultEx.getData();
        if (ObjectUtil.isEmpty(userVo)) {
            return ResultEx.fail("客户信息获取失败");
        }

        String userId = userVo.getUserId();
        CustProdConfigVo vo = new CustProdConfigVo();
        vo.setCustomerCode(custProdDetailVo.getCustomerCode());
        vo.setUserId(userId);
        vo.setProdCode(custProdDetailVo.getProdCode());
        vo.setAppId(custProdDetailVo.getAppId());
        vo.setAppSecret(custProdDetailVo.getAppSecret());
        vo.setUserPuk(custProdDetailVo.getUserPuk());
        return ResultEx.ok(vo);
    }

    public ResultEx checkWhitelist(String appId, String ip) {

        CustProdDetailVo custProdDetailVo = custProdService.getCustProdDetail(appId);

        if (ObjectUtil.isEmpty(custProdDetailVo) || !ProductOpenStatusEnum.NORMAL.getValue().equals(custProdDetailVo.getStatus())) {
            return ResultEx.fail();
        }

        //校验参数ip，是否在白名单列表内
        String whitelist = custProdDetailVo.getWhitelist();
        if (ObjectUtil.isEmpty(whitelist) || !whitelist.contains(ip)) {
            return ResultEx.fail();
        }

        return ResultEx.ok();
    }

    public ResultEx<String> sign(SignDto signDto) {
        CustProdConfig custProdConfig = custProdConfigService.getOne(new LambdaQueryWrapper<CustProdConfig>()
                .eq(CustProdConfig::getAppId, signDto.getAppId()));

        if (ObjectUtil.isEmpty(custProdConfig)) {
            return ResultEx.makeResult(PlatformRetCodeEnum.AP_NO_RESULT);
        }
        //平台私钥
        String privateKey = tradeOpenProperties.getPlatformPrk();
        //商户秘钥
        String secret = custProdConfig.getAppSecret();

        JSONObject jsonObject = signDto.getJsonObject();
        String signStr = SignUtil.signRsa(jsonObject, secret, privateKey);

        return ResultEx.ok(signStr);
    }

    public ResultEx checkSign(VerifySignDto checkSignDto) {
        if (!mdbProdProperties.isCheckSign()) {
            return ResultEx.ok(Boolean.TRUE);
        }

        ResultEx checkOpenApiAuth = this.checkOpenApiAuth(checkSignDto.getAppId());
        if (checkOpenApiAuth.isFailed()) {
            return checkOpenApiAuth;
        }

        //查询客户产品状态及puk
        CustProdConfig custProdConfig = custProdConfigService.getOne(new LambdaQueryWrapper<CustProdConfig>()
                .eq(CustProdConfig::getAppId, checkSignDto.getAppId()));

        if (ObjectUtil.isEmpty(custProdConfig)) {
            return ResultEx.fail();
        }

        if (ObjectUtil.isEmpty(custProdConfig.getUserPuk())) {
            //需先上传puk
            return ResultEx.makeResult(PlatformRetCodeEnum.APP_PUK_IS_NULL);
        }

        //根据appId获取对应的公钥及AppSecret
        String puk = custProdConfig.getUserPuk();
        String secret = custProdConfig.getAppSecret();

        JSONObject jsonObject = JSONObject.parseObject(checkSignDto.getJsonObject());
        if (ObjectUtil.isEmpty(jsonObject)) {
            jsonObject = new JSONObject();

        }
        jsonObject.put(ReqHeaderKeyEnum.APP.getValue(), checkSignDto.getApp());
        jsonObject.put(ReqHeaderKeyEnum.APP_ID.getValue(), checkSignDto.getAppId());

        boolean verifyResult = SignUtil.verifySignRsa(jsonObject, secret, checkSignDto.getSign(), puk);
        return verifyResult ? ResultEx.ok(verifyResult) : ResultEx.fail("验签失败");
    }

    public ResultEx<Boolean> setWhitelist(SetWhiteListDto setWhiteListDto) {
        CustProdConfig custProdConfig = custProdConfigService.getOne(new LambdaQueryWrapper<CustProdConfig>()
                .eq(CustProdConfig::getAppId, setWhiteListDto.getAppId()));

        if (ObjectUtil.isEmpty(custProdConfig)) {
            return ResultEx.fail();
        }

        //需验签 加签
        CustProd customerProd = new CustProd();
        customerProd.setWhitelist(setWhiteListDto.getWhitelist());

        boolean result = custProdService.update(customerProd, new LambdaUpdateWrapper<CustProd>()
                .eq(CustProd::getCustomerCode, custProdConfig.getCustomerCode())
                .eq(CustProd::getProdCode, custProdConfig.getProdCode()));
        return ResultEx.ok(result);
    }

    /**
     * 检查是否允许OPENAPI调用
     */
    public ResultEx<CustProdDetailVo> checkOpenApiAuth(String appId) {
        CustProdDetailVo custProdDetailVo = custProdService.getCustProdDetail(appId);
        if (ObjectUtil.isEmpty(custProdDetailVo)) {
            return ResultEx.makeResult(PlatformRetCodeEnum.PRODUCT_NOT_OPEN);
        }
        if (!ProductOpenStatusEnum.NORMAL.getValue().equals(custProdDetailVo.getStatus())) {
            return ResultEx.makeResult(PlatformRetCodeEnum.PRODUCT_STATUS_ERROR);
        }
        if (!custProdDetailVo.getDockingType().contains(ProdDockingTypeEnum.API.getValue())) {
            return ResultEx.makeResult(PlatformRetCodeEnum.OPEN_API_NOT_OPEN);
        }
        return ResultEx.ok(custProdDetailVo);
    }
}